package com.xyht.sca_s.student_manage_system.modules.waterMark.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.MultipartFileToFileUtils;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.waterMark.entity.SmsWaterMarkRecord;
import com.xyht.sca_s.student_manage_system.modules.waterMark.entity.req.SmsWaterMarkRecordReq;
import com.xyht.sca_s.student_manage_system.modules.waterMark.entity.resp.SmsWaterMarkRecordResp;
import com.xyht.sca_s.student_manage_system.modules.waterMark.mapper.SmsWaterMarkRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.waterMark.service.SmsWaterMarkService;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;

import static com.xyht.sca_s.student_manage_system.modules.waterMark.constant.CommonConstant.MAX_PAGES;
import static com.xyht.sca_s.student_manage_system.modules.waterMark.constant.RecordStatusConstant.*;

/**
 * <p>
 * 合同水印院校图标 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-02-19
 */
@Service
public class SmsWaterMarkServiceImpl implements SmsWaterMarkService {
    @Resource
    private SmsWaterMarkRecordMapper smsWaterMarkRecordMapper;
    @Resource
    private FileSavePathConstant fileSavePathConstant;

    @Override
    @Async
    public Future<ResponseResult> pdfWaterMarkAdd(String user_id, String name, Integer nameSpace, Float opacity, Integer imgSize,
                                                  Integer colorR, Integer colorG, Integer colorB, Float fontSize,
                                                  MultipartFile pdfFile, MultipartFile logoFile, HttpServletResponse response) {
        if (pdfFile.isEmpty()) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        if (nameSpace < 100) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WATER_MARK_NAMESPACE_ERR));
        }
        if (colorR * colorG * colorB < 0 || (colorR + colorG + colorB > 765)) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WATER_MARK_RGB_ERR));
        }
        if (fontSize < 0) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WATER_MARK_FONT_ERR));
        }

        if (!logoFile.isEmpty()) {
            if (imgSize < 0) {
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WATER_MARK_IMG_ERR));
            }
        }

        String fileName = pdfFile.getOriginalFilename();
        String suffix;
        if (fileName == null || fileName.lastIndexOf(".") == -1) {
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FILE_TYPE_ERR));
        } else {
            suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (!suffix.equals("pdf")) {
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FILE_TYPE_ERR));
            }
        }
        String timeStamp = new Date().getTime() + "";
        String newFileName = timeStamp + "." + suffix;
        String logeFileName = "logo_"+timeStamp+ ".png";

        //保存记录
        SmsWaterMarkRecord addRecord = new SmsWaterMarkRecord();
        addRecord.setRecordStatus(RECORD_STATUS_DOING);
        addRecord.setUserId(user_id);
        addRecord.setFileOldName(fileName);
        addRecord.setFileNewName(newFileName);
        smsWaterMarkRecordMapper.insert(addRecord);

        try {
            String OSName = System.getProperty("os.name");
            String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getWATER_MARK_DOWNLOAD_PATH()
                    : fileSavePathConstant.getWATER_MARK_DOWNLOAD_PATH_LINUX();
            String targetPath = filePath + newFileName;
            String logoPath = filePath + logeFileName;
            File saveFile = new File(targetPath);

            InputStream inputStream = pdfFile.getInputStream();
            // 加载PDF文档
            PDDocument doc = PDDocument.load(inputStream);
            doc.setAllSecurityToBeRemoved(true);
            // 创建水印
            PDPageContentStream contentStream;
            int pages = doc.getNumberOfPages();
            if (pages > MAX_PAGES) {
                updateRecordStatus(addRecord.getId(), RECORD_STATUS_ERR);
                return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.WATER_MARK_PAGES_MAX));
            }
            for (PDPage page : doc.getPages()) {
                contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);

                //加载字体
                ClassPathResource resource = new ClassPathResource("fonts/123.ttf");
                InputStream is = resource.getInputStream();
//                PDFont font = PDType0Font.load(doc, is);


                int startX = 0; // 起始位置 x 坐标
                int startY = 0; // 起始位置 y 坐标
                float angle = 0; // 角度
                float interval = nameSpace; // 间隔
                float opacity1 = opacity; // 透明度
                int colorR1 = colorR; // 颜色 red 值
                int colorG1 = colorG; // 颜色 green 值
                int colorB1 = colorB; // 颜色 blue 值

                //透明的
                PDExtendedGraphicsState r0 = new PDExtendedGraphicsState();
                r0.setNonStrokingAlphaConstant(opacity1);
                r0.setAlphaSourceFlag(true);
                contentStream.setGraphicsStateParameters(r0);

                int x_times = (int) Math.ceil(page.getMediaBox().getWidth() / interval);
                int y_times = (int) Math.ceil(page.getMediaBox().getHeight() / interval);

//                //水印颜色
//                contentStream.setNonStrokingColor(colorR1, colorG1, colorB1);
//                contentStream.beginText();
//                contentStream.setFont(font, fontSize);
//
//                for (int x = startX; x <= x_times; x++) {
//                    for (int y = startY; y <= y_times; y++) {
//                        contentStream.setTextRotation(angle, (x * interval + imgSize + 5), (y * interval + 3));
//                        contentStream.showText(name);
//                    }
//                }
//                contentStream.endText();

                //图片水印
                File file = MultipartFileToFileUtils.multipartFileToFile(logoFile,logoPath);
                if (!logoFile.isEmpty()) {
                    for (int x = startX; x <= x_times; x++) {
                        for (int y = startY; y <= y_times; y++) {
                            PDImageXObject pdImageXObject = PDImageXObject.createFromFileByExtension(file, doc);
                            contentStream.drawImage(pdImageXObject, (x * interval), (y * interval), imgSize, imgSize);
                        }
                    }
                }

                contentStream.restoreGraphicsState();
                contentStream.close();
                is.close();
            }

            // 保存PDF文档
            doc.save(saveFile);
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
            updateRecordStatus(addRecord.getId(), RECORD_STATUS_ERR);
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }

        //修改记录
        updateRecordStatus(addRecord.getId(), RECORD_STATUS_FINISH);
        return new AsyncResult<>(CommonResult.success());
    }

    @Override
    public ResponseResult getWaterMarkRecord(Integer pageNum, Integer pageSize, String user_id) {
        Page<SmsWaterMarkRecord> page = new Page<>(pageNum, pageSize);
        smsWaterMarkRecordMapper.selectPage(page, new LambdaQueryWrapper<SmsWaterMarkRecord>()
                .eq(SmsWaterMarkRecord::getUserId, user_id)
                .orderByDesc(SmsWaterMarkRecord::getCreateTime));
        List<SmsWaterMarkRecordResp> list = page.getRecords()
                .stream()
                .map(record->{
                    SmsWaterMarkRecordResp waterMarkRecordResp = new SmsWaterMarkRecordResp();
                    BeanUtils.copyProperties(record,waterMarkRecordResp);
                    return waterMarkRecordResp;
                })
                .collect(Collectors.toList());
        int total = (int) page.getTotal();
        return CommonResult.success(list,total);
    }

    @Override
    public ResponseResult deleteWaterMartRecord(SmsWaterMarkRecordReq recordReq, String user_id) {
        if (isNullOrEmpty(recordReq.getId())){
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        smsWaterMarkRecordMapper.delete(new LambdaQueryWrapper<SmsWaterMarkRecord>()
                .eq(SmsWaterMarkRecord::getId,recordReq.getId())
                .eq(SmsWaterMarkRecord::getUserId,user_id));
        return CommonResult.success();
    }

    private void updateRecordStatus(String record_id, int status) {
        SmsWaterMarkRecord updateRecord = new SmsWaterMarkRecord();
        updateRecord.setId(record_id);
        updateRecord.setRecordStatus(status);
        smsWaterMarkRecordMapper.updateById(updateRecord);
    }

}
